package mogodb;

import java.io.File;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import com.google.gson.Gson;

/**
 * 
 * @author csxx_wmw
 *
 */
public class UseDb implements Mogodb {

	private static final String TABLE_ELEMENT = "table";
	private static final String TABLE_ELEMENT_KEY = "name";
	private static final String TABLE_ELEMENT_VALUE_SYSTEM_DATA = "data";
	private static final String TABLE_ELEMENT_VALUE_SYSTEM_INDEX = "system.indexs";
	private static final String TABLE_ELEMENT_VALUE_SYSTEM_USER = "system.users";
	private static final String DATA_ELEMENT = "data";
	private static final String DATA_ELEMENT_KEY = "uuid";
	private static final String db_file = "src/mogodb/db.xml";

	public String dbName = "";

	public UseDb(String dbName) {
		this.dbName = dbName;
	}

	/**
	 * �������ݿ�
	 * 
	 * @param dbName
	 */
	public void createDb() {
		try {

			SAXBuilder builder = new SAXBuilder();
			Document document = builder.build(new File(db_file));
			Element dbsroot = document.getRootElement();
			if (dbsroot.getChild(dbName) != null) {
				System.out.println(dbName + "�Ѵ���");
				return;
			}

			Element dbElement = new Element(dbName);

			Element element1 = new Element(UseDb.TABLE_ELEMENT);
			Element element2 = new Element(UseDb.TABLE_ELEMENT);
			Element element3 = new Element(UseDb.TABLE_ELEMENT);
			element1.setAttribute(UseDb.TABLE_ELEMENT_KEY, UseDb.TABLE_ELEMENT_VALUE_SYSTEM_DATA);
			element2.setAttribute(UseDb.TABLE_ELEMENT_KEY, UseDb.TABLE_ELEMENT_VALUE_SYSTEM_INDEX);
			element3.setAttribute(UseDb.TABLE_ELEMENT_KEY, UseDb.TABLE_ELEMENT_VALUE_SYSTEM_USER);
			dbElement.addContent(element1);
			dbElement.addContent(element2);
			dbElement.addContent(element3);
			dbsroot.addContent(dbElement);
			XMLOutputter out = new XMLOutputter();
			out.output(document, new FileOutputStream(db_file));
			System.out.println("Create Success");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * ��ȡxml�ļ�
	 */
	private Document getDocument() {
		Document document = null;
		try {
			FileInputStream fis = new FileInputStream(db_file);
			SAXBuilder builder = new SAXBuilder();
			document = builder.build(fis);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return document;
	}

	/**
	 * ��ȡ���ݿ�����
	 * 
	 * @param dbName
	 * @return
	 */
	public List<Map<String, Object>> getDatas() {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		Gson gson = new Gson();
		Element rootElement = getDocument().getRootElement();
		Element dbElement = rootElement.getChild(dbName);
		List<Element> elementList = dbElement.getChildren();

		for (Element element : elementList) {
			if (element.getAttributeValue(UseDb.TABLE_ELEMENT_KEY).equals(UseDb.TABLE_ELEMENT_VALUE_SYSTEM_DATA)) {
				List<Element> dataElement = element.getChildren();
				for (Element element2 : dataElement) {
					String data = element2.getText();
					if (data == null) {
						break;
					}
					Map<String, Object> map = gson.fromJson(data, Map.class);
					result.add(map);
				}
			}
		}
		return result;
	}

	/**
	 * ��������
	 * 
	 * @param dbName
	 * @param obj
	 * @return
	 */
	public boolean insert(Object obj) {
		Gson gson = new Gson();
		Document document = getDocument();

		Element dbElement = document.getRootElement().getChild(dbName);
		List<Element> elementList = dbElement.getChildren();

		for (Element element : elementList) {
			if (element.getAttributeValue(UseDb.TABLE_ELEMENT_KEY).equals(UseDb.TABLE_ELEMENT_VALUE_SYSTEM_DATA)) {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put(UseDb.DATA_ELEMENT_KEY, UUID.randomUUID().toString());
				String json = gson.toJson(obj);
				Map<String, Object> dMap = gson.fromJson(json, Map.class);
				map.putAll(dMap);
				Element data = new Element(UseDb.DATA_ELEMENT);
				data.addContent(gson.toJson(map));
				element.addContent(data);
			}
		}
		XMLOutputter out = new XMLOutputter();
		boolean flag = false;
		try {
			out.output(document, new FileOutputStream(db_file));
			flag = true;
			System.out.println("insert success");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * ��������
	 * 
	 * @param obj
	 * @param dbname
	 * @return
	 */
	public boolean updateData(Object obj) {
		Gson gson = new Gson();
		Document document = getDocument();

		Element dbElement = document.getRootElement().getChild(dbName);

		List<Element> elements = dbElement.getChildren();

		for (Element element : elements) {
			if (element.getAttributeValue(UseDb.TABLE_ELEMENT_KEY).equals(UseDb.TABLE_ELEMENT_VALUE_SYSTEM_DATA)) {
				List<Element> datas = element.getChildren();
				for (Element element2 : datas) {
					Map<String, Object> dMap = gson.fromJson(element2.getText(), Map.class);
					Map<String, Object> updateMap = gson.fromJson(gson.toJson(obj), Map.class);
					if (dMap.get(UseDb.DATA_ELEMENT_KEY).equals(updateMap.get(UseDb.DATA_ELEMENT_KEY))) {
						dMap.putAll(updateMap);
						Element data = new Element(UseDb.DATA_ELEMENT);
						data.setText(gson.toJson(dMap));
						element.removeContent(element2);
						element.addContent(data);
						break;
					}
				}
			}
		}

		boolean flag = false;
		XMLOutputter out = new XMLOutputter();
		try {
			out.output(document, new FileOutputStream(db_file));
			flag = true;
			System.out.println("update success");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * ɾ������
	 * 
	 * @param filePath
	 * @param obj
	 * @return
	 */
	public boolean deleteData(Object obj) {
		Gson gson = new Gson();
		Document document = getDocument();
		Element dbElement = document.getRootElement().getChild(dbName);
		List<Element> elements = dbElement.getChildren();
		for (Element element : elements) {
			if (element.getAttributeValue(UseDb.TABLE_ELEMENT_KEY).equals(UseDb.TABLE_ELEMENT_VALUE_SYSTEM_DATA)) {
				List<Element> datas = element.getChildren();
				for (Element element2 : datas) {
					Map<String, Object> dMap = gson.fromJson(element2.getText(), Map.class);
					Map<String, Object> deleteMap = gson.fromJson(gson.toJson(obj), Map.class);
					if (dMap.get(UseDb.DATA_ELEMENT_KEY).equals(deleteMap.get(UseDb.DATA_ELEMENT_KEY))) {
						element.removeContent(element2);
						break;
					}
				}
			}
		}

		boolean flag = false;
		XMLOutputter out = new XMLOutputter();
		try {
			out.output(document, new FileOutputStream(db_file));
			flag = true;
			System.out.println("delete success");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return flag;
	}
}
